package com.bytecub.utils;


import java.nio.ByteBuffer;

public class ByteUtils {

    private static final String[] zeroNum = {"", "0", "00", "000", "0000", "00000", "000000",
            "0000000"};
    private static final byte[] sign1 = {(byte) 128, (byte) 64, (byte) 32, (byte) 16, (byte) 8,
            (byte) 4, (byte) 2, (byte) 1,};


    public static void main(String[] args) {
//    char[] a = "012345".toCharArray();
//    byte[] b = new byte[a.length];
//    for (int i = 0; i < a.length; i++) {
//      b[i] = (byte) (a[i] - '0');
//    }
//    System.out.println(ByteUtils.bytesToHex(b));
//    ====================================
//    byte[] result = {1, 0, 0, 0, 0, 0};
//    Long longValue = lowByte2Long(result);
//    System.out.println(longValue);
//    ====================================
//    byte[] resultInteger = {1, 0, 0};
//    Integer integer = lowByte2Int(resultInteger);
//    System.out.println(integer);
//    ====================================
//    byte[] src = {(byte) 0x01, (byte) 0x00, (byte) 0x00};
//    System.out.println(byte2Long(src));
//    ====================================
//    byte[] result = int2Byte(2018);
//    System.out.println(result[0] < 0 ? result[0] + 256 : result[0]);
//    System.out.println(result[1] < 0 ? result[1] + 256 : result[1]);
//    System.out.println(result[2] < 0 ? result[2] + 256 : result[2]);
//    System.out.println(result[3] < 0 ? result[3] + 256 : result[3]);
//    ====================================
//    byte[] result = {(byte) 0xad, 3, 1, 1, 0x11, 1, 0, 8};
//    long checkSum = negSumCheck(result);
////    int f;
////    if (checkSum < 0) {
////      f = checkSum + 256;
////    } else {
////      f = checkSum;
////    }
////    byte d = (byte) ~f;
////    d += 1;
////    System.out.println(d);
//    System.out.println(checkSum);
//    ====================================
//    System.out.println(ByteUtils.bytesToHex(string2Bytes("012345")));
//    ====================================
//    System.out.println(bytes2IntBy4Bit(new byte[]{8, 7, 3}));
//    ====================================
//    byte[] result = {(byte) 0xff, (byte) 0x10, (byte) 0xa0, (byte) 0x00, (byte) 0x01};
//    String str = result.toString();
//    byte[] copyResult = str.getBytes();
//    System.out.println(copyResult);
//    ====================================
//    byte[] bytes = new byte[]{(byte) 0x28, (byte) 0x83, (byte) 0xA5, (byte) 0x3C, (byte) 0xFE,
//        (byte) 0xB6};
//    long result = lowByte2Long(bytes);
//    System.out.println(result);
//    byte[] results = longToBytes(result);
//    System.out.println(results);
//    ====================================
//    longToBytes(2919358664856174592l);
//    ====================================
        byte[] bytes = {0x01, 0x02, 0x3, 0x4};
        System.out.println(conver2HexStr(bytes));
    }

    private static int[] intArray = new int[]{1, 10, 100, 1000, 10000, 100000};

    /**
     * int按位转成byte数组每4比特位，低字节在高位
     */
    public static byte[] int2BytesBy4Bit(int _4Bit) {
        byte[] bytes = new byte[3];
        int imd, index;
        for (int i = 0; intArray.length > i; i++) {
            imd = _4Bit / intArray[i] % 10;
            index = (int) Math.ceil((intArray.length - i) / 2.0) - 1;
            if (i % 2 == 0) {
                bytes[index] |= imd;
            } else {
                bytes[index] |= (imd << 4);
            }
        }
        return bytes;
    }

    /**
     * 8位字节数组转换为长整型，高字节在低位
     */
    public static Long lowByte2Long(byte[] bytes) {
        byte[] all = new byte[8];
        for (int i = 0; i < 8; i++) {
            if (bytes.length > i) {
                all[i] = bytes[i];
            } else {
                all[i] = 0;
            }
        }
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.put(all, 0, 8);
        buffer.flip();//need flip
        return buffer.getLong();
    }

    public static byte[] longToBytes(long x) {
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.putLong(0, x);
        return buffer.array();
    }

    /**
     * 数组按4比特位转成int类型，低字节在高位
     */
    public static int bytes2IntBy4Bit(byte[] bytes) {
        int all = 0;
        for (int i = 0; i < 4 && bytes.length > i; i++) {
            all += (bytes[i] >> 4 & 0x0f) * ((int) (Math.pow(10, (bytes.length - i - 1) * 2 + 1)));
            all += (bytes[i] & 0x0f) * ((int) (Math.pow(10, (bytes.length - i - 1) * 2)));
        }
        return all;
    }

    /**
     * 字符串按字符对应byte4位
     */
    public static byte[] string2Bytes(String string) {
        char[] chars = string.toCharArray();
        byte[] bytes = new byte[chars.length / 2];
        for (int i = 0; i < chars.length; i++) {
            if (i % 2 == 0) {
                bytes[i / 2] = (byte) ((((chars[i] - '0') & 0xff) << 4) | bytes[i / 2]);
            } else {
                bytes[i / 2] = (byte) ((chars[i] - '0') | bytes[i / 2]);
            }
        }
        return bytes;
    }

    /**
     * 4位字节数组转换为整型，高字节在低位
     */
    public static Integer lowByte2Int(byte[] b) {
        Integer intValue = 0;
        for (int i = (b.length - 1); i >= 0; i--) {
            intValue += (b[i] & 0xFF) << (8 * (b.length - 1 - i));
        }
        return intValue;
    }

    public static char byteToChar(byte[] b) {
        char c = (char) (((b[0] & 0xFF) << 8) | (b[1] & 0xFF));
        return c;
    }

    public static String asciiToString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append((char) b);
        }
        return sb.toString();
    }

    /**
     * 累加校验和
     *
     * @param msg 需要计算校验和的byte数组
     * @return 计算出的校验和数组
     */
    public static long SumCheck(byte... msg) {
        long mSum = 0;
        for (byte byteMsg : msg) {
            if (byteMsg < 0) {
                mSum += (byteMsg + 256);
            } else {
                mSum += byteMsg;
            }
        }
        return mSum;
    }


    /**
     * 累加校验和
     *
     * @param msg 需要计算校验和的byte数组
     * @return 计算出的校验和数组
     */
    public static byte negSumCheck(byte... msg) {
        long mSum = 0;
        for (byte byteMsg : msg) {
            if (byteMsg < 0) {
                mSum += (byteMsg + 256);
            } else {
                mSum += byteMsg;
            }
        }
        byte f = (byte) ~mSum;
        byte add = (byte) (f + ((byte) 1));
        return add;
    }

    public static byte SumCheck(byte[]... msg) {
        byte[] charge;
        int length = 0, l = 0;
        /** 逐Byte添加位数和 */
        for (byte[] byteMsg : msg) {
            length += byteMsg.length;
        }
        charge = new byte[length];
        l = 0;
        for (byte[] byteMsg : msg) {
            System.arraycopy(byteMsg, 0, charge, l, byteMsg.length);
            l += byteMsg.length;
        }
        return (byte) SumCheck(charge);
    }

    /**
     * 字节转输出为二进制字符串，逗号隔开
     */
    public static String conver2HexStr(byte[] b) {
        StringBuffer result = new StringBuffer();
        String str;
        for (int i = 0; i < b.length; i++) {
            str = Integer.toString(b[i] & 0xff, 2);
            result.append(zeroNum[(8 - str.length())] + str + ",");
        }
        return result.toString().substring(0, result.length() - 1);
    }

    /**
     * 字节转输出为十六进制字符串，逗号隔开
     */
    final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();

    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }

    /**
     * 把16进制字符串转换成字节数组
     *
     * @return byte[]
     */
    public static byte[] hexStringToByte(String hex) {
        int len = (hex.length() / 2);
        byte[] result = new byte[len];
        char[] achar = hex.toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
        }
        return result;
    }

    private static int toByte(char c) {
        byte b = (byte) "0123456789ABCDEF".indexOf(c);
        return b;
    }

    public static byte[] conver2Bytes(String str, String sign) {
        String[] strings = str.split(sign);
//        String pattern = "[0,1]";
        byte[] result = new byte[strings.length];
        for (int i = 0; i < strings.length; i++) {
//            if (Pattern.matches(pattern, strings[i])) {
            byte[] rb = strings[i].getBytes();
            for (int j = rb.length - 1; j > 0; j--) {
                if ((byte) 49 == rb[j]) {
                    result[i] |= sign1[j];
                }
            }
        }
        return result;
    }

    public static byte[] getBytesFromBytes(byte[] src, int start, int length) {
        byte[] descBytes = new byte[length];
        System.arraycopy(src, start, descBytes, 0, length);
        return descBytes;
    }

    /**
     * byte数组转long类型，低字节在前面
     */
    public static Long byte2Long(byte[] src) {
        Long longValue = 0l;
        for (int i = 0; i < src.length; i++) {
            longValue += (src[i] & 0xFF) << (8 * (src.length - 1 - i));
        }
        return longValue;
    }

    public static byte[] yearValue2Bytes2(int year) {
        byte[] bytes = new byte[2];
        bytes[0] = (byte) (year / 100);
        bytes[1] = (byte) (year % 100);
        return bytes;
    }

    /**
     * 整型转换为4位字节数组
     */
    public static byte[] int2Byte(int intValue) {
        byte[] b = new byte[4];
        for (int i = 0; i < 4; i++) {
            b[i] = (byte) (intValue >> 8 * (3 - i) & 0xFF);
        }
        return b;
    }

    /**
     * 整型转换为4位字节数组
     */
    public static byte[] long2Byte(long intValue) {
        byte[] b = new byte[8];
        for (int i = 0; i < 8; i++) {
            b[i] = (byte) (intValue >> 8 * (3 - i) & 0xFF);
        }
        return b;
    }

    /**
     * 4位字节数组转换为整型,高字节在高位
     */
    public static Integer byte2Int(byte[] b) {
        Integer intValue = 0;
        for (int i = 0; i < b.length; i++) {
            intValue += (b[i] & 0xFF) << (8 * (3 - i));
        }
        return intValue;
    }


    public static byte SumCheck(byte[] src, byte[] desc, int length) {
        byte[] bytes = new byte[src.length + desc.length];
        System.arraycopy(src, 0, bytes, 0, src.length);
        System.arraycopy(desc, 0, bytes, src.length, desc.length);
        return (byte) SumCheck(bytes);
    }

    public static byte[] string2Bytes(String guid, String s) {
        String[] srcStr = guid.split(s);
        if (srcStr.length != 6) {
            return null;
        }
        byte[] outputs = new byte[srcStr.length];
        for (int i = 0; i < outputs.length; i++) {
            outputs[i] = (byte) Integer.parseInt(srcStr[i], 2);
        }
        return outputs;
    }

    public static byte[] charToByte(char c) {
        byte[] b = new byte[2];
        b[0] = (byte) ((c & 0xFF00) >> 8);
        b[1] = (byte) (c & 0xFF);
        return b;
    }

    public static String bytes2StringBy4(byte[] bytes) {

        StringBuffer result = new StringBuffer();
        String str;
        for (int i = 0; i < bytes.length; i++) {
            str = Integer.toString(bytes[i] & 0xff, 2);
            StringBuilder insertStr = new StringBuilder(zeroNum[(8 - str.length())] + str);
            insertStr.insert(4, ",");
            result.append(insertStr + ",");
        }
        return result.toString().substring(0, result.length() - 1);
    }

    public static byte[] stringBy42Bytes(String result) {
        String[] strings = result.split(",");
        byte[] results = new byte[4];
        for (int i = 0; i < strings.length / 2; i++) {
            results[i] = (byte) Integer.parseInt(strings[i * 2] + strings[i * 2 + 1], 2);
        }
        return results;
    }
}
